import { Service } from 'egg';
import { Department } from '../model/Department';
import { Employee } from '../model/Employee';

export default class DepartmentService extends Service {
    /**
     * 创建部门
     * @param param 
     */
    public async createDepartment(param: any) {
        try {
            param.department_name = this.ctx.helper.trim(param.department_name);
            const checkResult = await this.ctx.model.Department.findOne<Department>({ attributes: ['department_id'], where: { department_name: param.department_name, is_delete: '0' } });
            if (checkResult) {
                throw new Error(JSON.stringify({ code: 2, msg: '该部门名称已存在，不能重复添加' }));
            }
            const submitData: any = {};
            //生成主键id
            submitData.department_id = this.ctx.helper.genUUID();
            submitData.department_name = param.department_name;
            submitData.created_by = param.admin_id;
            submitData.is_delete = '0';
            const position_id = param.position_id;
            if (!position_id) {
                const result: any = await this.ctx.model.Department.create(submitData);
                if (!result) {
                    throw new Error(JSON.stringify({ code: 2, msg: '创建失败' }));
                }
            } else {
                const position_id_list = position_id.split(',');
                const positionArr: any = [];
                for (let i = 0; i < position_id_list.length; i++) {
                    const item: any = {};
                    //生成主键
                    item.department_postion_id = this.ctx.helper.genUUID();
                    item.department_id = submitData.department_id;
                    item.position_id = position_id_list[i];
                    item.is_delete = '0';
                    positionArr.push(item);
                }
                //新建事务
                const tran = await this.ctx.model.transaction();
                try {
                    await this.ctx.model.Department.create(submitData, { transaction: tran });
                    if (positionArr.length > 0) {
                        await this.ctx.model.DepartmentPosition.bulkCreate(positionArr, { transaction: tran });
                    }
                    await tran.commit();
                } catch (e) {
                    await tran.rollback();
                    this.ctx.logger.error(e);
                    throw new Error(JSON.stringify({ code: 2, msg: '创建失败' }));
                }
            }
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }

    /**
     * 删除部门
     * @param param 
     */
    public async deleteDepartment(param: any) {
        try {
            const department_id = param.department_id;
            const searchEmployeeParam = { department_id, type: 1 };
            const employee = await this.searchEmployeeByDepartment(searchEmployeeParam);
            if (employee.length > 0) {
                throw new Error(JSON.stringify({ code: 2, msg: '该部门存在职员不能删除，如想删除，请先到职员管理，解绑或者删除相关职员' }));
            }
            const admin_id = param.admin_id;
            const tran = await this.ctx.model.transaction();
            try {
                const deleteResult = await this.ctx.model.Department.update({ updated_by: admin_id, is_delete: '1' }, { where: { department_id }, transaction: tran });
                if (deleteResult[0] <= 0) {
                    throw new Error(JSON.stringify({ code: 2, msg: '删除失败' }));
                }
                await this.ctx.model.DepartmentPosition.destroy({ where: { department_id }, transaction: tran });
                await tran.commit();
            } catch (e) {
                await tran.rollback();
                this.ctx.logger.error(e);
                throw new Error(JSON.stringify({ code: 2, msg: '删除失败' }));
            }
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }

    /**
     * 查找部门
     * @param param 
     */
    public async searchDepartment() {
        try {
            const result: any = await this.ctx.model.Department.findAll<Department>({ attributes: ['department_id', 'department_name'], where: { is_delete: '0' }, order: [['created_at', 'DESC']] });
            if (result.length <= 0) {
                throw new Error(JSON.stringify({ code: 2, msg: '没有数据' }));
            }
            //查找在职员工数和职位数
            const returnData: any = [];
            for (let i = 0; i < result.length; i++) {
                const department_id = result[i].department_id;
                const item: any = {};
                item.department_id = department_id;
                item.department_name = result[i].department_name;
                const queryStr = `
            select p.position_id,p.position_name from t_department_position d inner join t_position p 
            on d.department_id=:department_id and d.position_id=p.position_id and p.is_delete='0' where d.is_delete='0'`;
                const positionResult: any = await this.ctx.model.query(queryStr, {
                    type: this.ctx.model.QueryTypes.SELECT,
                    replacements: { department_id }
                })
                item.position_num = positionResult.length;
                const employee: any = await this.ctx.model.Employee.count({ where: { department_id: item.department_id, is_delete: '0', employee_status: '2' } });
                item.employee_num = employee;
                returnData.push(item);
            }
            return returnData;
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }

    /**
     * 根据部门id查找部门信息
     * @param param 
     */
    public async searchDepartmentById(param: any) {
        try {
            const department_id = param.department_id;
            const result: any = await this.ctx.model.Department.findOne<Department>({ attributes: ['department_name'], where: { department_id, is_delete: '0' } });
            if (!result) {
                throw new Error(JSON.stringify({ code: 2, msg: '找不到这个部门' }));
            }
            const returnData: any = {};
            returnData.department_id = department_id;
            returnData.department_name = result.department_name;
            const queryStr = `
            select p.position_id,p.position_name from t_department_position d inner join t_position p 
            on d.department_id=:department_id and d.position_id=p.position_id and p.is_delete='0' where d.is_delete='0'`;
            const positionResult: any = await this.ctx.model.query(queryStr, {
                type: this.ctx.model.QueryTypes.SELECT,
                replacements: { department_id }
            })
            if (positionResult.length <= 0) {
                returnData.positionList = [];
            } else {
                returnData.positionList = positionResult;
            }
            return returnData;
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }

    /**
     * 修改部门
     * @param param 
     */
    public async updateDepartment(param: any) {
        try {
            param.department_name = this.ctx.helper.trim(param.department_name);
            const queryStr = `select department_id from t_department where department_name=:department_name and is_delete='0' and department_id not in (:department_id)`;
            const checkIsRepeatResult = await this.ctx.model.query(queryStr, {
                type: this.ctx.model.QueryTypes.SELECT,
                replacements: { department_name: param.department_name, department_id: param.department_id }
            });
            if (checkIsRepeatResult.length > 0) {
                throw new Error(JSON.stringify({ code: 2, msg: '该部门名称已存在，修改失败' }));
            }
            const admin_id = param.admin_id;
            const department_id = param.department_id;
            const department_name = param.department_name;
            const position_id = param.position_id;
            const searchEmployeeParam = { department_id, type: 2 };
            const employee = await this.searchEmployeeByDepartment(searchEmployeeParam);
            const position_id_list = position_id.split(',');
            let checkResult = true;
            for (let i = 0; i < employee.length; i++) {
                let hasPosition = false;
                for (let j = 0; j < position_id_list.length; j++) {
                    if (employee[i].position_id == position_id_list[j]) {
                        hasPosition = true;
                        break;
                    }
                }
                if (hasPosition) {
                    continue;
                } else {
                    checkResult = false;
                }
            }
            if (!checkResult) {
                throw new Error(JSON.stringify({ code: 2, msg: '该部门所属职位存在职员，不能删除有职员的职位，如想删除，请先到职员管理，解绑或者删除相关职员' }));
            }
            if (!position_id) {
                const tran = await this.ctx.model.transaction();
                try {
                    const updateResult: any = await this.ctx.model.Department.update({ department_name, updated_by: admin_id }, { where: { department_id }, transaction: tran });
                    if (updateResult[0] <= 0) {
                        throw new Error(JSON.stringify({ code: 2, msg: '修改失败' }));
                    }
                    await this.ctx.model.DepartmentPosition.destroy({ where: { department_id }, transaction: tran });
                    await tran.commit();
                } catch (e) {
                    await tran.rollback();
                    this.ctx.logger.error(e);
                    throw new Error(JSON.stringify({ code: 2, msg: '修改失败' }));
                }
            } else {
                const position_id_list = position_id.split(',');
                const positionArr: any = [];
                for (let i = 0; i < position_id_list.length; i++) {
                    const item: any = {};
                    //生成主键
                    item.department_postion_id = this.ctx.helper.genUUID();
                    item.department_id = department_id;
                    item.position_id = position_id_list[i];
                    item.is_delete = '0';
                    positionArr.push(item);
                }
                //新建事务
                const tran = await this.ctx.model.transaction();
                try {
                    const updateResult: any = await this.ctx.model.Department.update({ department_name, updated_by: admin_id }, { where: { department_id }, transaction: tran });
                    if (updateResult[0] <= 0) {
                        throw new Error(JSON.stringify({ code: 2, msg: '修改失败' }));
                    }
                    await this.ctx.model.DepartmentPosition.destroy({ where: { department_id }, transaction: tran });
                    if (positionArr.length > 0) {
                        await this.ctx.model.DepartmentPosition.bulkCreate(positionArr, { transaction: tran });
                    }
                    await tran.commit();
                } catch (e) {
                    await tran.rollback();
                    this.ctx.logger.error(e);
                    throw new Error(JSON.stringify({ code: 2, msg: '修改失败' }));
                }
            }
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }

    /**
     * 根据部门找职员
     * @param param 
     */
    public async searchEmployeeByDepartment(param: any) {
        try {
            const department_id = param.department_id;
            const type = param.type;
            if (type == 1) {
                const result: any = await this.ctx.model.Employee.findAll<Employee>({ attributes: ['employee_id'], where: { department_id, is_delete: '0' } });
                return result;
            } else if (type == 2) {
                const queryStr = `select position_id from t_employee where department_id=:department_id and is_delete='0' group by position_id`;
                const result: any = await this.ctx.model.query(queryStr, {
                    type: this.ctx.model.QueryTypes.SELECT,
                    replacements: { department_id }
                })
                return result;
            }
        } catch (e) {
            this.ctx.logger.error(e);
            throw new Error(e.message);
        }
    }
}